/*
 ***************************************************************
 ***************************************************************
 * / __| /_\ |  \/  | __/ __| _ \_ _|   \    (_)__ ___ ____ _*** 
 *| (_ |/ _ \| |\/| | _| (_ |   /| || |) |_  | / _` \ V / _` |**
 * \___/_/ \_\_|  |_|___\___|_|_\___|___/(_)_/ \__,_|\_/\__,_|**
 ******************************************|__/*****************               
 ***************************************************************
 */
package othello.logic;

import java.util.ArrayList;
import java.util.List;

public class GameGrid {
    //GameGrid dimensions.
    private final int HEIGHT = 8;
    private final int WIDTH = 8;
    
    //Constants for player color.
    private final int EMPTY = 0;
    private final int BLACK = 1;
    private final int WHITE = 2;
    private int[][] gameGrid = new int[HEIGHT][WIDTH];

    public GameGrid() {
        clearGrid();
    }
    
    public void clearGrid(){
        //Initiate/clear grid. 
        for (int i = 0; i < HEIGHT; i++) {
            for (int j = 0; j < WIDTH; j++) {
                gameGrid[i][j] = EMPTY;
            }
        }

        //Starting tiles.
        gameGrid[3][3] = WHITE;
        gameGrid[3][4] = BLACK;
        gameGrid[4][3] = BLACK;
        gameGrid[4][4] = WHITE;
    }

    public int[][] getGrid() {
        return gameGrid;
    }
    
    //Makes the move
    public boolean makeMove(int color, Coordinates coords) {
        if (gameGrid[coords.getX()][coords.getY()] != EMPTY) {
            return false;
        }

        if (checkAdjacent(coords, color)) {
            gameGrid[coords.getX()][coords.getY()] = color;
            return true;
        }
        return false;
    }
    
    //Checks if the move wanted, is valid.
    public boolean validMove(int color, Coordinates coords) {
        if (gameGrid[coords.getX()][coords.getY()] != EMPTY) {
            return false;
        }

        return(validMoveCheckAdjacent(coords, color)); 
    }

    private boolean checkAdjacent(Coordinates coords, int color) {

        int diffColor = BLACK;
        boolean ture = false;

        if (color == BLACK) {
            diffColor = WHITE;
        }

        if (coords.getX() > 0 && coords.getY() > 0) {
            if (gameGrid[coords.getX() - 1][coords.getY() - 1] == diffColor) {
                if (checkLine(new Coordinates(coords.getX() - 1, coords.getY() - 1), new Coordinates(-1, -1), color)) {
                    ture = true;
                }
            }
        }

        if (coords.getY() > 0) {
            if (gameGrid[coords.getX()][coords.getY() - 1] == diffColor) {
                if (checkLine(new Coordinates(coords.getX(), coords.getY() - 1), new Coordinates(-0, -1), color)) {
                    ture = true;
                }
            }
        }

        if (coords.getX() < 7 && coords.getY() > 0) {
            if (gameGrid[coords.getX() + 1][coords.getY() - 1] == diffColor) {
                if (checkLine(new Coordinates(coords.getX() + 1, coords.getY() - 1), new Coordinates(1, -1), color)) {
                    ture = true;
                }
            }
        }

        if (coords.getX() < 7) {
            if (gameGrid[coords.getX() + 1][coords.getY()] == diffColor) {
                if (checkLine(new Coordinates(coords.getX() + 1, coords.getY()), new Coordinates(1, 0), color)) {
                    ture = true;
                }
            }
        }

        if (coords.getX() < 7 && coords.getY() < 7) {
            if (gameGrid[coords.getX() + 1][coords.getY() + 1] == diffColor) {
                if (checkLine(new Coordinates(coords.getX() + 1, coords.getY() + 1), new Coordinates(1, 1), color)) {
                    ture = true;
                }
            }
        }

        if (coords.getY() < 7) {
            if (gameGrid[coords.getX()][coords.getY() + 1] == diffColor) {
                if (checkLine(new Coordinates(coords.getX(), coords.getY() + 1), new Coordinates(0, 1), color)) {
                    ture = true;
                }
            }
        }

        if (coords.getX() > 0 && coords.getY() < 7) {
            if (gameGrid[coords.getX() - 1][coords.getY() + 1] == diffColor) {
                if (checkLine(new Coordinates(coords.getX() - 1, coords.getY() + 1), new Coordinates(-1, 1), color)) {
                    ture = true;
                }
            }
        }

        if (coords.getX() > 0) {
            if (gameGrid[coords.getX() - 1][coords.getY()] == diffColor) {
                if (checkLine(new Coordinates(coords.getX() - 1, coords.getY()), new Coordinates(-1, 0), color)) {
                    ture = true;
                }
            }
        }
        return ture;
    }

    private boolean checkLine(Coordinates source, Coordinates difference, int color) {
        if (source.getX() > 7 || source.getX() < 0 || source.getY() > 7 || source.getY() < 0 || gameGrid[source.getX()][source.getY()] == EMPTY) {
            return false;
        }

        if (gameGrid[source.getX()][source.getY()] == color) {
            return true;
        }

        if (checkLine(new Coordinates(source.getX() + difference.getX(), source.getY() + difference.getY()), difference, color)) {
            gameGrid[source.getX()][source.getY()] = color;
            return true;
        }
        return false;
    }
    
    private boolean validMoveCheckAdjacent(Coordinates coords, int color) {

        int diffColor = BLACK;
        boolean ture = false;

        if (color == BLACK) {
            diffColor = WHITE;
        }

        if (coords.getX() > 0 && coords.getY() > 0) {
            if (gameGrid[coords.getX() - 1][coords.getY() - 1] == diffColor) {
                if (validMoveCheckLine(new Coordinates(coords.getX() - 1, coords.getY() - 1), new Coordinates(-1, -1), color)) {
                    ture = true;
                }
            }
        }

        if (coords.getY() > 0) {
            if (gameGrid[coords.getX()][coords.getY() - 1] == diffColor) {
                if (validMoveCheckLine(new Coordinates(coords.getX(), coords.getY() - 1), new Coordinates(-0, -1), color)) {
                    ture = true;
                }
            }
        }

        if (coords.getX() < 7 && coords.getY() > 0) {
            if (gameGrid[coords.getX() + 1][coords.getY() - 1] == diffColor) {
                if (validMoveCheckLine(new Coordinates(coords.getX() + 1, coords.getY() - 1), new Coordinates(1, -1), color)) {
                    ture = true;
                }
            }
        }

        if (coords.getX() < 7) {
            if (gameGrid[coords.getX() + 1][coords.getY()] == diffColor) {
                if (validMoveCheckLine(new Coordinates(coords.getX() + 1, coords.getY()), new Coordinates(1, 0), color)) {
                    ture = true;
                }
            }
        }

        if (coords.getX() < 7 && coords.getY() < 7) {
            if (gameGrid[coords.getX() + 1][coords.getY() + 1] == diffColor) {
                if (validMoveCheckLine(new Coordinates(coords.getX() + 1, coords.getY() + 1), new Coordinates(1, 1), color)) {
                    ture = true;
                }
            }
        }

        if (coords.getY() < 7) {
            if (gameGrid[coords.getX()][coords.getY() + 1] == diffColor) {
                if (validMoveCheckLine(new Coordinates(coords.getX(), coords.getY() + 1), new Coordinates(0, 1), color)) {
                    ture = true;
                }
            }
        }

        if (coords.getX() > 0 && coords.getY() < 7) {
            if (gameGrid[coords.getX() - 1][coords.getY() + 1] == diffColor) {
                if (validMoveCheckLine(new Coordinates(coords.getX() - 1, coords.getY() + 1), new Coordinates(-1, 1), color)) {
                    ture = true;
                }
            }
        }

        if (coords.getX() > 0) {
            if (gameGrid[coords.getX() - 1][coords.getY()] == diffColor) {
                if (validMoveCheckLine(new Coordinates(coords.getX() - 1, coords.getY()), new Coordinates(-1, 0), color)) {
                    ture = true;
                }
            }
        }
        return ture;
    }
    
    private boolean validMoveCheckLine(Coordinates source, Coordinates difference, int color) {
        if (source.getX() > 7 || source.getX() < 0 || source.getY() > 7 || source.getY() < 0 || gameGrid[source.getX()][source.getY()] == EMPTY) {
            return false;
        }

        if (gameGrid[source.getX()][source.getY()] == color) {
            return true;
        }

        if (checkLine(new Coordinates(source.getX() + difference.getX(), source.getY() + difference.getY()), difference, color)) {
            return true;
        }
        return false;
    }

    //Checks who is the winner, by calculating the tiles.
    public int countWinner() {
        int black = 0, white = 0;
                
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                if(gameGrid[i][j] == BLACK)
                    black += 1;
                if(gameGrid[i][j] == WHITE)
                    white += 1;
            } 
        }
        if(black == white)
            return -1;
        if(black > white)
            return BLACK;
        else
            return WHITE;
    }
}
